library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity alu is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
			  y : out STD_LOGIC_VECTOR(15 downto 0);
           c : out  STD_LOGIC :='1';
           z : out  STD_LOGIC);
end alu;

architecture Behavioral of alu is
	signal sig : STD_LOGIC_VECTOR(3 downto 0) := "0000";
	signal a : STD_LOGIC_VECTOR(15 downto 0) :="0000000000000001";
	signal b : STD_LOGIC_VECTOR(15 downto 0) :="0000000000000010";
	signal cin : STD_LOGIC := '0';
begin
	process(clk)
	begin
		if(clk'event and clk='1') then
			if(sig="1000" or rst='1') then
				sig <= "0000";
			else
				sig <= sig + 1;
			end if;
		end if;
	end process;
	
	process(sig)
	variable output : STD_LOGIC_VECTOR(15 downto 0);
	variable i_sum : STD_LOGIC_VECTOR(16 downto 0);
	constant i_cin_ext: STD_LOGIC_VECTOR(16 downto 1) := (others => '0');
	begin
		--rol
		if(sig="0000") then
			output := To_StdLogicVector(TO_BITVECTOR(a) rol CONV_INTEGER(b));
		end if;
		--sra
		if(sig="0001") then
			output := To_StdLogicVector(TO_BITVECTOR(a) sra CONV_INTEGER(b));
		end if;
		--sll
		if(sig="0010") then
			output := To_StdLogicVector(TO_BITVECTOR(a) sll CONV_INTEGER(b));
		end if;
		--not
		if(sig="0011") then
			output := not a;
		end if;
		--xor
		if(sig="0100") then
			output := a xor b;
		end if;
		--or
		if(sig="0101") then
			output := a or b;
		end if;
		--and
		if(sig="0110") then
			output := a and b;
		end if;
		--sub
		if(sig="0111") then
			i_sum := ('0' & a) - ('0' & b) - (i_cin_ext & cin); 
			output := i_sum(15 downto 0); 
			c <= i_sum(16); 
		end if;
		--add
		if(sig="1000") then
			i_sum := ('0' & a) + ('0' & b) + (i_cin_ext & cin); 
			output := i_sum(15 downto 0); 
			c <= i_sum(16); 
		end if;

		if(output="0000000000000000") then
			z <= '1';
		else 
			z <= '0';
		end if;
		
		y <= output;
		
	end process;
end Behavioral;


